
/*
 * Copyright 2009, Center for Advanced Information Systems,Nanyang Technological University
 *
 * File name: GBlendView.java
 *
 * Abstract: The application's main frame
 *
 * Current Version:      0.1
 * Auther:               Jin Changjiu
 * Modified Date:        Feb 28,2009
 *
 */
package gblend;

import gblend.adjlistgraph.ALGraph;
import gblend.adjlistgraph.FsgIdEntry;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import javax.swing.JComponent;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.FrameView;

import java.util.Vector;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.Task;
import gblend.db.AddDBTask;
import gblend.db.AddDbDialog;
import gblend.db.DatabaseInfo;

import gblend.util.ButtonTabComponent;
import gblend.util.DemoGraphScene;
import gblend.db.LoadingDialog;

import gblend.db.Parameters;
import gblend.exactquery.BuildQuery;
import gblend.exactquery.SNode;
import gblend.util.BuildIndexTask;
import gblend.exactquery.MatchedGraph;
import gblend.exactquery.QueryEngine;
import gblend.exactquery.ExactVerify;
import gblend.result.InfoChart;
import gblend.similarity.SimilarQuery;
import gblend.util.RunTime;
import org.jfree.ui.RefineryUtilities;
import zgrviewer.ZGRViewer;

public class GBlendView extends FrameView {

    private DemoGraphScene scene = new DemoGraphScene();
    private JComponent myView;
    private JTabbedPane pane = new JTabbedPane();
    private int tabnum = 0;
    private DatabaseInfo databaseInfo = null;
    private ExactVerify ev = null;
    private RunTime time = new RunTime();
    private int finalnum = 0;
    private Parameters parameters = null;
    private BuildIndexTask task = null;
    private ZGRViewer viewer = null;
    private InfoChart chart = new InfoChart("Real Time Query Charts");

    public GBlendView(SingleFrameApplication app) throws SQLException {

        super(app);
        initComponents();
        initFrame();
        ResourceMap resourceMap = getResourceMap();
        super.getFrame().setIconImage(resourceMap.getImageIcon("logo").getImage());

    }

    private void initFrame() throws SQLException {

        this.DatabasePanel.add(GBlendApp.getDbManager().getView());
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = GBlendApp.getApplication().getMainFrame();
            aboutBox = new GBlendAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        GBlendApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jSplitPane1 = new javax.swing.JSplitPane();
        DatabasePanel = new javax.swing.JPanel();
        QueryPanel = new javax.swing.JPanel();
        drawPane = new javax.swing.JScrollPane();
        jToolBar1 = new javax.swing.JToolBar();
        addDatabaseButton = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        IndexButton = new javax.swing.JButton();
        addQueryButton = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        runButton = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JToolBar.Separator();
        resultButton = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        dbMenu = new javax.swing.JMenu();
        queryMenu = new javax.swing.JMenu();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();

        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setLayout(new java.awt.BorderLayout());

        jSplitPane1.setName("jSplitPane1"); // NOI18N

        DatabasePanel.setName("DatabasePanel"); // NOI18N
        DatabasePanel.setPreferredSize(new java.awt.Dimension(100, 300));
        DatabasePanel.setLayout(new java.awt.BorderLayout());
        jSplitPane1.setLeftComponent(DatabasePanel);

        QueryPanel.setName("QueryPanel"); // NOI18N
        QueryPanel.setLayout(new java.awt.BorderLayout());

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance().getContext().getResourceMap(GBlendView.class);
        drawPane.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("drawPane.border.title"))); // NOI18N
        drawPane.setMinimumSize(new java.awt.Dimension(200, 200));
        drawPane.setName("drawPane"); // NOI18N
        drawPane.setPreferredSize(new java.awt.Dimension(300, 400));
        QueryPanel.add(drawPane, java.awt.BorderLayout.PAGE_START);

        jSplitPane1.setRightComponent(QueryPanel);

        mainPanel.add(jSplitPane1, java.awt.BorderLayout.CENTER);

        jToolBar1.setRollover(true);
        jToolBar1.setName("jToolBar1"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance().getContext().getActionMap(GBlendView.class, this);
        addDatabaseButton.setAction(actionMap.get("addDatabase")); // NOI18N
        addDatabaseButton.setFocusable(false);
        addDatabaseButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        addDatabaseButton.setName("addDatabaseButton"); // NOI18N
        addDatabaseButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(addDatabaseButton);

        jSeparator1.setName("jSeparator1"); // NOI18N
        jToolBar1.add(jSeparator1);

        IndexButton.setAction(actionMap.get("buildIndex")); // NOI18N
        IndexButton.setText(resourceMap.getString("IndexButton.text")); // NOI18N
        IndexButton.setFocusable(false);
        IndexButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        IndexButton.setName("IndexButton"); // NOI18N
        IndexButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        IndexButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                IndexButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(IndexButton);

        addQueryButton.setAction(actionMap.get("addQuery")); // NOI18N
        addQueryButton.setFocusable(false);
        addQueryButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        addQueryButton.setName("addQueryButton"); // NOI18N
        addQueryButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        addQueryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addQueryButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(addQueryButton);

        jSeparator2.setName("jSeparator2"); // NOI18N
        jToolBar1.add(jSeparator2);

        runButton.setAction(actionMap.get("run")); // NOI18N
        runButton.setFocusable(false);
        runButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        runButton.setName("runButton"); // NOI18N
        runButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        runButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                runButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(runButton);

        jSeparator3.setName("jSeparator3"); // NOI18N
        jToolBar1.add(jSeparator3);

        resultButton.setAction(actionMap.get("showresult")); // NOI18N
        resultButton.setFocusable(false);
        resultButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        resultButton.setName("resultButton"); // NOI18N
        resultButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        resultButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resultButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(resultButton);

        mainPanel.add(jToolBar1, java.awt.BorderLayout.PAGE_START);

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        dbMenu.setText(resourceMap.getString("dbMenu.text")); // NOI18N
        dbMenu.setName("dbMenu"); // NOI18N
        menuBar.add(dbMenu);

        queryMenu.setText(resourceMap.getString("queryMenu.text")); // NOI18N
        queryMenu.setName("queryMenu"); // NOI18N
        menuBar.add(queryMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 431, Short.MAX_VALUE)
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(17, 17, 17))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

private void addQueryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addQueryButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_addQueryButtonActionPerformed

private void resultButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_resultButtonActionPerformed

private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_runButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_runButtonActionPerformed

private void IndexButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_IndexButtonActionPerformed
    // TODO add your handling code here:
}//GEN-LAST:event_IndexButtonActionPerformed
    @Action
    public Task addDatabase() throws SQLException, IOException {

        AddDbDialog dialog = new AddDbDialog(this.getFrame(), true);
        dialog.setResizable(false);
        dialog.setTitle("Add Database");
        GBlendApp.getApplication().show(dialog);
        if (dialog.getReturnStatus() == AddDbDialog.RET_CANCEL) {
            return null;
        }
        databaseInfo = dialog.getDatabaseInfo();
        parameters = dialog.getParameters();

        AddDBTask task = new AddDBTask(databaseInfo);
        task.addPropertyChangeListener(LoadingDialog.createDialog(this.getFrame(), task, true));
        return task;

    }

    @Action
    public void addQuery() throws ClassNotFoundException, SQLException {

        if (databaseInfo == null || task == null)//if didn't choose database, show this dialog
        {
            String message = "Please select the Database and build the index firstly!";
            JOptionPane.showConfirmDialog(this.getFrame(), message, "Error", JOptionPane.PLAIN_MESSAGE);
        } else {
            scene = new DemoGraphScene();
            myView = scene.createView();
            this.drawPane.setViewportView(myView);
            this.QueryPanel.add(pane);

            pane.removeAll();
            String title = "Query " + (++tabnum);
            pane.add(title, drawPane);
            pane.setTabComponentAt(0, new ButtonTabComponent(pane));
            pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
            scene.getQueryIndex().getQueryMatch().setDBcon(databaseInfo, parameters);

            chart.setVisible(true);
            chart.dispose();
            RefineryUtilities.centerFrameOnScreen(chart);
            chart.setSize(450, 350);
            scene.getQueryIndex().setFrame(chart);

        }


    }

    @Action
    public void run() throws SQLException, ClassNotFoundException, FileNotFoundException {

        //record the final result graphs
        Vector<ALGraph> resultGraphs = new Vector<ALGraph>();
        //store the final graph ids
        Vector<FsgIdEntry> results = new Vector<FsgIdEntry>();
        //record the matched subgraphs in the results
        Vector<MatchedGraph> mGraphs = new Vector<MatchedGraph>();

        BuildQuery bq = scene.getQueryIndex();
        QueryEngine qengine = bq.getQueryMatch();
        SNode query = bq.getWholeQuery();

        System.out.println("\nQuery formulation time(s): " + bq.getformulationtime());
        String msg = "Exact Results Number: ";

        time.time[RunTime.RUN_START] = System.nanoTime();

        if (qengine.getQuerytype() == 2)//for the common infrequent
        {
            ev = new ExactVerify();
            mGraphs = ev.verify(query, qengine);//verify the exact results from candidates
            for (int i = 0; i < mGraphs.size(); i++) {
                //  MatchedGraph tmpG =mGraphs.elementAt(i);
                //  FsgIdEntry rfId = tmpG.getid();

                results.addElement(mGraphs.elementAt(i).getid());
            }
            resultGraphs = ev.getExactResults();
        } else if (qengine.getQuerytype() < 2)//without verification
        {
            results.addAll(qengine.getCandidateIds());
        }

        int exact = results.size();
        System.out.println("Exact Query size: " + results.size());
        for (int i = 0; i < exact; i++) {
            System.out.println(results.get(i));
        }
        //if the results of exact query is 0, set it as similarity query
        SimilarQuery sq = bq.getSQ();

        /*if(results.isEmpty())
        {*/
        //   if(qengine.getQuerytype()!=3)
        //   {
        sq.simCandidateCalculate(query, qengine);//get the candidate set
        //    }

        sq.finalSimVerify(query, qengine, results, mGraphs);
        resultGraphs.addAll(sq.getApproGraphs());
        msg = msg + exact + "\nSimilar Results Number: ";
        //  }

        time.time[RunTime.RUN_END] = System.nanoTime();//SRT ends
        time.time[RunTime.USED] = time.time[RunTime.RUN_END] - time.time[RunTime.RUN_START];
        float finaltime = (int) Math.round(time.time[RunTime.USED] / 1000) / (float) 1000;
        finalnum = results.size();
        System.out.println("Simaliar query size: " + (results.size() - exact));
        for (int i = 0; i < finalnum; i++) {
            System.out.println(results.get(i));
        }

        String message = msg + (finalnum - exact) + "\n\nSystem Response Time(ms): " + finaltime;
        System.out.println("System Response Time (ms): " + finaltime);
        Object[] options = {"View Results", "Exit"};

        int n = JOptionPane.showOptionDialog(this.getFrame(),
                message, "Query Results",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE,
                null, options, options[0]);

        //prepare the graph view
        if (n == JOptionPane.YES_OPTION && finalnum != 0) {
            viewer = new ZGRViewer(qengine, databaseInfo, results, mGraphs, query, resultGraphs);
        }

    }

    @Action
    public void showresult() {
        if (finalnum != 0) {
            viewer.review();
        }
    }

    @Action
    public Task buildIndex() {

        QueryEngine qengine = scene.getQueryIndex().getQueryMatch();
        qengine.getinfindex().setDBcon(databaseInfo);
        task = new BuildIndexTask(qengine.getfindex(), qengine.getinfindex(), parameters);
        task.addPropertyChangeListener(LoadingDialog.createDialog(this.getFrame(), task, true));
        return task;

    }

    public int initateDialogue() {
        String message = "Current query has no exact Results";
        Object[] options = {"Modify the Query", "Similarity Search"};
        int n = JOptionPane.showOptionDialog(mainPanel,
                message, "Query Options",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE,
                null, options, options[0]);
        return n;
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel DatabasePanel;
    private javax.swing.JButton IndexButton;
    private javax.swing.JPanel QueryPanel;
    private javax.swing.JButton addDatabaseButton;
    private javax.swing.JButton addQueryButton;
    private javax.swing.JMenu dbMenu;
    private javax.swing.JScrollPane drawPane;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JToolBar.Separator jSeparator3;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenu queryMenu;
    private javax.swing.JButton resultButton;
    private javax.swing.JButton runButton;
    private javax.swing.JPanel statusPanel;
    // End of variables declaration//GEN-END:variables
    private JDialog aboutBox;
}
